#include "stdafx.h"
#include <string>
#include <boost/test/auto_unit_test.hpp>

namespace bmock
{
	static std::string generate_err_indicator_str(const size_t counter, const size_t line_length)
	{
		std::string str(counter % (line_length), ' ');
		str += "^\n";			
		str.insert(0, std::string(strlen("EXPECTED:  "), ' '));

		return str;
	}

	static void fail(const char *fileName, const size_t line,const char *expected,const char *actual,
					 const size_t counter_expected, const size_t counter_actual)
	{
		const size_t line_length = 160;

		std::string exp_str(expected-counter_expected);
		std::string act_str(actual-counter_actual, strlen(actual-counter_actual));

		std::string final_str = "";
		for (size_t i = 0; i < exp_str.size() || i < act_str.size(); i = i + line_length)
		{
			if (i < exp_str.size()) 
			{
				final_str += ("EXPECTED:  " + exp_str.substr(i, line_length) + "\n");
				if (counter_expected >= i && counter_expected <= i + line_length)
				{
					final_str += generate_err_indicator_str(counter_expected, line_length);
				}
			}
			if (i < act_str.size())
			{
				final_str += ("ACTUAL:    " + act_str.substr(i, line_length) + "\n");
				if (counter_actual >= i && counter_actual <= i + line_length)
				{
					final_str += generate_err_indicator_str(counter_actual, line_length);
				}
			}
		}

		boost::test_toolbox::tt_detail::check_impl(false
			,boost::unit_test::lazy_ostream::instance()	<< "SL_PP: expected != actual: \n\n"
			<< final_str << "\n"
			,fileName
			,line
			,boost::test_toolbox::tt_detail::REQUIRE
			,boost::test_toolbox::tt_detail::CHECK_MSG,0);	
	}

	static std::string omit_extra_spaces(const char *expected, const char *actual)
	{
		std::string actual_spaces_omitted = "";

		const char *end_actual = actual + strlen(actual) - 1;
		++actual; 

		while ( *expected && (end_actual != actual) ) 
		{
			if (' ' != *expected && ' ' == *actual)
			{
				++actual;
				continue;
			}
			actual_spaces_omitted.push_back(*actual++);
			expected++;
		}

		while (end_actual != actual) 
		{
			actual_spaces_omitted.push_back(*actual++);
		}

		return actual_spaces_omitted;
	}	

	void __sl_pp_compare(const char *fileName, const size_t line, const std::string& expected_str, const char *actual) 
	{
		const char* expected = expected_str.c_str();
		std::string actual_spaces_omitted = omit_extra_spaces(expected, actual);
		const char *new_actual = actual_spaces_omitted.c_str();
		const char *end_actual = new_actual + strlen(new_actual);

		size_t counter_expected = 0;
		size_t counter_actual = 0;

		while ( *expected && (end_actual != new_actual) )
		{
			if(*expected != *new_actual)
			{
				fail(fileName,line, expected, new_actual, counter_expected, counter_actual);
				return;
			}
			++expected;
			++counter_expected;
			++new_actual;		
			++counter_actual;
		}

		while ((end_actual != new_actual) && (' ' == *new_actual)) 
		{
			++new_actual;
			++counter_actual;
		}
		if ( *expected || (end_actual != new_actual) ) 
		{
			fail(fileName,line, expected, new_actual, counter_expected, counter_actual);
		}
	}
}